﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.Three
{
    public static class Box3Ext
    {
        public static Box3 SetFromBufferAttribute(this Box3 box, BufferAttribute attribute)
        {
            var _vector = Box3.GetContext()._vector;
            box.MakeEmpty();
            for (int i = 0, il = attribute.count; i < il; i++)
            {
                box.ExpandByPoint(_vector.FromBufferAttribute(attribute, i));
            }

            return box;
        }

        public static Box3 SetFromObject(this Box3 box, Object3D _object, bool precise = false)
        {
            box.MakeEmpty();
            return box.ExpandByObject(_object, precise);
        }
        public static Box3 ExpandByObject(this Box3 box,Object3D _object, bool precise = false)
        {
            var ctx = Box3.GetContext();
            var _vector = ctx._vector;
            var _box = ctx._box;
            // Computes the world-axis-aligned bounding box of an object (including its children),
            // accounting for both the object"s, and children"s, world transforms
            _object.updateWorldMatrix(false, false);

            if (_object == null || !(_object is IGeometry))
                return box;

            if (_object.HasField("boundingBox"))
            {
                if (_object.GetField("boundingBox") == null)
                {
                    _object.InvokeMethod("computeBoundingBox");
                }

                _box.Copy(_object.GetField("boundingBox") as Box3);
                _box.ApplyMatrix4(_object.matrixWorld);

                box.Union(_box);

            }
            else
            {
                var geometry = (_object as IGeometry).getGeometry();

                if (geometry != null)
                {
                    if (precise && geometry.attributes != null && geometry.attributes["position"] != null)
                    {
                        var position = geometry.attributes["position"];
                        for (int i = 0, l = position.count; i < l; i++)
                        {
                            _vector.FromBufferAttribute(position, i).ApplyMatrix4(_object.matrixWorld);
                            box.ExpandByPoint(_vector);
                        }
                    }
                    else
                    {
                        if (geometry.boundingBox == null)
                        {
                            geometry.computeBoundingBox();
                        }
                        _box.Copy(geometry.boundingBox);
                        _box.ApplyMatrix4(_object.matrixWorld);
                        box.Union(_box);
                    }
                }

            }
            var children = _object.children;
            for (int i = 0, l = children.Length; i < l; i++)
            {
                box.ExpandByObject(children[i], precise);
            }
            return box;
        }

    }
}
